package com.cicigodd.brick.plug.security.operate;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.cicigodd.brick.plug.security.api.ResourceCollectorApi;
import com.cicigodd.brick.plug.security.resource.entity.SysResource;
import com.cicigodd.brick.plug.security.resource.request.SysResourceAddRequest;
import com.cicigodd.brick.plug.security.resource.service.SysResourceService;
import com.cicigodd.brick.plug.security.scanner.ResourceDefinition;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 默认的资源收集器，默认搜集到内存Map中
 *
 * @author cicigodd
 * @date 2020/10/19 20:33
 */
@Service
public class DefaultResourceCollector implements ResourceCollectorApi {

    /**
     * 以资源编码为key，存放资源集合
     */
    private final Map<String, ResourceDefinition> resourceDefinitions = new ConcurrentHashMap<>();


    /**
     * key是请求的url，value是资源信息
     */
    private final Map<String, ResourceDefinition> urlDefineResources = new ConcurrentHashMap<>();

    @Resource
    private SysResourceService sysResourceService;

    @Value("${server.servlet.context-path}")
    private String contextPath;

    @Override
    public void collectResources(List<ResourceDefinition> apiResource) {
        if (apiResource != null && apiResource.size() > 0) {
            for (ResourceDefinition resourceDefinition : apiResource) {
                String url = "";
                if (ObjectUtil.isNotEmpty(contextPath)) {
                    url = contextPath + resourceDefinition.getUrl();
                } else {
                    url = resourceDefinition.getUrl();
                }

                resourceDefinitions.put(resourceDefinition.getResourceCode(), resourceDefinition);
                urlDefineResources.put(url, resourceDefinition);
                //保存到数据库
                LambdaQueryWrapper<SysResource> wrapper = new LambdaQueryWrapper<>();
                wrapper.eq(SysResource::getResourceCode,resourceDefinition.getResourceCode());
                sysResourceService.remove(wrapper);
                SysResourceAddRequest sysResourceAddRequest = new SysResourceAddRequest();
                sysResourceAddRequest.setResourceCode(resourceDefinition.getResourceCode());
                sysResourceAddRequest.setResourceName(resourceDefinition.getResourceName());
                sysResourceAddRequest.setClassName(resourceDefinition.getClassName());
                sysResourceAddRequest.setMethodName(resourceDefinition.getMethodName());
                sysResourceAddRequest.setUrl(url);
                sysResourceAddRequest.setHttpMethod(resourceDefinition.getHttpMethod());
                sysResourceAddRequest.setRequiredPermissionFlag(resourceDefinition.getRequiredPermissionFlag() ? "Y" : "N");
                sysResourceService.add(sysResourceAddRequest);
            }
        }
    }

    @Override
    public ResourceDefinition getResource(String resourceCode) {
        return resourceDefinitions.get(resourceCode);
    }

    @Override
    public List<ResourceDefinition> getAllResources() {
        Set<Map.Entry<String, ResourceDefinition>> entries = resourceDefinitions.entrySet();
        ArrayList<ResourceDefinition> resourceDefinitions = new ArrayList<>();
        for (Map.Entry<String, ResourceDefinition> entry : entries) {
            resourceDefinitions.add(entry.getValue());
        }
        return resourceDefinitions;
    }


    @Override
    public String getResourceUrl(String code) {
        ResourceDefinition resourceDefinition = this.resourceDefinitions.get(code);
        if (resourceDefinition == null) {
            return null;
        } else {
            return resourceDefinition.getUrl();
        }
    }

    @Override
    public ResourceDefinition getResourceByUrl(String url) {
        return this.urlDefineResources.get(url);
    }

    @Override
    public Integer getAllResourceCount() {
        return this.resourceDefinitions.size();
    }

    /**
     * 校验接口是否需要权限过滤
     * @param url
     * @return
     */
    @Override
    public Boolean checkPermission(String url) {
        ResourceDefinition resourceDefinition = this.urlDefineResources.get(url);
        if(ObjectUtil.isNotNull(resourceDefinition)){
            return resourceDefinition.getRequiredPermissionFlag();
        }
        return true;
    }
}
